package no.gnet.edvd.database.inmemory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import no.gnet.edvd.DataStore;
import no.gnet.edvd.engines.EventOdds;
import no.gnet.edvd.feed.types.RemoteMatch;
import no.gnet.edvd.statemachine.BetState;
import no.gnet.edvd.types.Activity;
import no.gnet.edvd.types.ActivityType;
import no.gnet.edvd.types.Bet;
import no.gnet.edvd.types.Category;
import no.gnet.edvd.types.Comment;
import no.gnet.edvd.types.Currency;
import no.gnet.edvd.types.Event;
import no.gnet.edvd.types.EventType;
import no.gnet.edvd.types.FacebookUser;
import no.gnet.edvd.types.MatchEvent;
import no.gnet.edvd.types.Option;
import no.gnet.edvd.types.PaymentAccount;
import no.gnet.edvd.types.Player;
import no.gnet.edvd.types.Transfer;
import no.gnet.edvd.types.Wallet;

import org.joda.time.DateTime;

public class InMemoryDatastore implements DataStore {

	private Hashtable<Integer, Bet> bets;
	private Hashtable<Integer, Event> events;
	private Hashtable<Integer, Option> winners;
	private Hashtable<Integer, Option> options;
	private Hashtable<Integer, Player> players;
	private Hashtable<Integer, Currency> currencies;
	private Hashtable<Integer, Comment> comments;
	private Hashtable<Integer, Wallet> wallets;
	private Hashtable<Integer, List<String>> tags;
	private Hashtable<Integer, List<Activity>> activityLogs;

	private Hashtable<Integer, FacebookUser> fbusers;

	private static int autinc_id = 0;

	public InMemoryDatastore() {
		bets = new Hashtable<Integer, Bet>();
		events = new Hashtable<Integer, Event>();
		options = new Hashtable<Integer, Option>();
		players = new Hashtable<Integer, Player>();
		fbusers = new Hashtable<Integer, FacebookUser>();
		comments = new Hashtable<Integer, Comment>();
		wallets = new Hashtable<Integer, Wallet>();
		tags = new Hashtable<Integer, List<String>>();
		activityLogs = new Hashtable<Integer, List<Activity>>();
		winners = new Hashtable<Integer, Option>();
	}

	@Override
	public int placeBet(Bet bet) {
		if (events.get(bet.event.id) == null) {
			throw new IllegalStateException("Event " + bet.event.id
					+ " does not exist");
		}
		bets.put(bet.id, bet);
		return bet.id;
	}

	@Override
	public void placeBets(Bet... bets) {
		for (int i = 0; i < bets.length; i++) {
			placeBet(bets[i]);
		}
	}

	@Override
	public void updateBet(Bet bet) {
		bets.put(bet.id, bet);

	}

	@Override
	public Bet getBet(Bet bet) {
		return bets.get(bet.id);

	}

	@Override
	public Event storeEvent(Event event) {
		events.put(event.id, event);
		List<Option> opts = event.getOptions();
		if (opts != null) {
			for (Iterator<Option> iterator = opts.iterator(); iterator
					.hasNext();) {
				Option o = iterator.next();
				options.put(o.id, o);
			}
		}
		return event;
	}

	@Override
	public void updateEvent(Event event) {
		events.put(event.id, event);
	}

	@Override
	public List<Bet> getBetsForEvent(Event event) {
		return _getBets(event.id);
	}

	private List<Bet> _getBets(int eventid) {
		Enumeration<Integer> keys = bets.keys();
		List<Bet> betsForEvent = new ArrayList<Bet>();
		while (keys.hasMoreElements()) {
			Bet bet = bets.get(keys.nextElement());
			if (bet.event.id == eventid) {
				betsForEvent.add(bet);
			}
		}
		return betsForEvent;
	}

	public static int inVMautoInc() {
		autinc_id++;
		return autinc_id;
	}

	@Override
	public List<Bet> getBetsForEvent(int eventid) {
		return _getBets(eventid);
	}

	@Override
	public List<Event> listEvents(boolean populatePlayers) {
		ArrayList<Event> eventlist = new ArrayList<Event>();
		Collection<Event> eventcollection = events.values();
		eventlist.addAll(eventcollection);
		return eventlist;
	}

	@Override
	public void insertCurrency(Currency currency) {
		currencies.put(inVMautoInc(), currency);
	}

	@Override
	public Player storePlayer(Player player) {
		Player p = player;
		p.id = inVMautoInc();
		players.put(p.id, p);
		return p;
	}

	@Override
	public boolean playerExists(Player player) {
		Enumeration<Player> enumer = players.elements();
		while (enumer.hasMoreElements()) {
			Player object = (Player) enumer.nextElement();
			if (object.equals(player))
				return true;
		}
		return false;
	}

	public Player getPlayer(Player jimmy) {
		return null;
	}

	@Override
	public boolean currenciesEstablished() {
		return true;
	}

	public List<Option> getOptionsForEvent(int eventid) {
		return null;
	}

	@Override
	public Event getBettableEvent(int iid) {
		return events.get(new Integer(iid));
	}

	@Override
	public Option getOption(int optionid) {
		return options.get(new Integer(optionid));
	}

	@Override
	public boolean eventTypesEstablished() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void insertEventType(EventType centrallyManaged) {
		// TODO Auto-generated method stub

	}

	@Override
	public FacebookUser getFBUser(String fbUserID, String email) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public FacebookUser insertFBUser(FacebookUser fbUser) {
		return fbUser;
	}

	@Override
	public Player getPlayer(int playerid) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getHashedPasswordForUser(String username) {
		// TODO Auto-generated method stub
		return "testpw";
	}

	@Override
	public Player storePlayerWithPassword(Player player, String pw) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void deleteTestUsers(String string) {
		// TODO Auto-generated method stub

	}

	@Override
	public void likeEvent(int eventid, Player player) {
		Event event = events.get(eventid);
		List<Player> likers = event.likers;
		if (likers == null) {
			likers = new ArrayList<Player>();
			event.likers = likers;
		}
		likers.add(player);
		event.likes++;
		event.setLikers(likers);
		events.put(event.id, event);
	}

	@Override
	public int getLikesForEvent(int eventid) {
		Event event = events.get(eventid);
		return event.likes;
	}

	@Override
	public boolean hasLiked(int eventid, int playerid) {
		Event event = events.get(eventid);
		List<Player> likers = event.likers;
		for (Iterator<Player> iterator = likers.iterator(); iterator.hasNext();) {
			Player player = iterator.next();
			if (player.id == playerid)
				return true;
		}
		return false;
	}

	@Override
	public List<Comment> loadCommentsForEvent(int event) {
		List<Comment> existing = new ArrayList<Comment>(comments.values());
		ArrayList<Comment> theones = new ArrayList<Comment>();
		for (Iterator iterator = existing.iterator(); iterator.hasNext();) {
			Comment comment = (Comment) iterator.next();
			if (comment.eventid == event) {
				theones.add(comment);
			}
		}
		return theones;
	}

	@Override
	public List<Bet> getUserBets(int id) {
		List<Bet> userbets = new ArrayList<Bet>();
		while (bets.keys().hasMoreElements()) {
			Integer key = (Integer) bets.keys().nextElement();
			Bet bet = bets.get(key);
			if (bet.player.id == id)
				userbets.add(bet);
		}
		return userbets;
	}

	@Override
	public void addComment(Player player, int event, String comment) {
		int cid = inVMautoInc();
		Comment comm = new Comment(cid, comment, player, event, new DateTime());
		comments.put(cid, comm);

	}

	@Override
	public List<Bet> getAllBetsForPlayer(int id) {
		List<Bet> userbets = new ArrayList<Bet>();
		while (bets.keys().hasMoreElements()) {
			Integer key = (Integer) bets.keys().nextElement();
			Bet bet = bets.get(key);
			if (bet.player.id == id)
				userbets.add(bet);
		}
		return userbets;
	}

	@Override
	public Wallet getWalletForUser(int id) {
		return new Wallet(10, 1, Currency.EURO);
	}

	@Override
	public int createEmptyStartupWalletForUser(Player player) {
		Wallet w = new Wallet(0.0, player.id, Currency.BETCOIN);
		return 0;

	}

	@Override
	public void deletePlayer(int uid) {
		// TODO Auto-generated method stub

	}

	@Override
	public void deletePlayerWithEmail(String email) {
		// TODO Auto-generated method stub

	}

	@Override
	public void updateWalletForUser(Wallet w, Player player) {
		Wallet wallet = wallets.get(player.id);
		wallet.setAmount(w.getAmount());
	}

	@Override
	public boolean categoriesEstablished() {
		return true;
	}

	@Override
	public void insertCategory(Category cat) {
	}

	@Override
	public List<String> getTagsForEvent(int id) {
		return tags.get(id);
	}

	@Override
	public void addTagsForEvent(int id, List<String> newtags) {
		List<String> taglist = tags.get(id);
		for (Iterator<String> iterator = taglist.iterator(); iterator.hasNext();) {
			String string = iterator.next();
			taglist.add(string);
		}
	}

	@Override
	public List<Activity> getActivityLogForPlayer(Player gautePlayer) {
		return activityLogs.get(gautePlayer.id);
	}

	@Override
	public void logActivity(ActivityType type, String text, Player player) {
		List<Activity> activityLog = activityLogs.get(player.id);
		if (activityLog == null) {
			activityLog = new ArrayList<Activity>();
		}
		Activity activity = new Activity(text, type, player);
		activityLog.add(activity);
	}

	@Override
	public void activateEvent(int eventid) {
		// TODO Auto-generated method stub

	}

	@Override
	public List<Event> getEventsInState(BetState state) {
		List<Event> allEvents = listEvents(false);
		List<Event> eventsInState = new ArrayList<Event>();
		for (Event event : allEvents) {
			if (event.state == state)
				eventsInState.add(event);
		}
		return eventsInState;
	}

	@Override
	public void transitionTo(Event event, BetState state) {
		// TODO Auto-generated method stub

	}

	@Override
	public void eventTimePassed(List<Event> events) {

	}

	@Override
	public Option getWinnerForEvent(Event event) {
		return winners.get(event.id);
	}

	@Override
	public List<Event> getEventsOwnedBy(int playerid) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Event getEventForDecision(int iid) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setWinnerForEvent(int eventid, int winner) {
		Event event = events.get(eventid);
		Option option = options.get(winner);
		event.setWinningOption(option);
		storeEvent(event);
		winners.put(eventid, option);
	}

	@Override
	public List<Event> betsToClose() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<Event> betsEventTimePassed() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void betsClosed(List<Event> events) {
		// TODO Auto-generated method stub

	}

	@Override
	public double settleBet(Bet bet, EventOdds eodds) {
		return 0.0;
	}

	@Override
	public void storeImportedMatchEvent(MatchEvent matchEvent,
			RemoteMatch rmatch) {
		// TODO Auto-generated method stub

	}

	@Override
	public void storeTransfer(Transfer transfer) {

	}

	@Override
	public List<Transfer> getUnsettledTransfersForUser(int player_id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public PaymentAccount getPaymentAccountForUser(int player_id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setPaymentAccountForUser(int player_id, String email) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setPaidTransfer(int transferid) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Event setMatchResult(int importedmatchid, String result) {
		return null;
	}

	@Override
	public String getMatchResult(int importedmatchid) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setPaymode(int playerid, boolean p2p) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void activatePlayer(int playerid) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean isActivated(int playerid) {
		return false;
		
	}
}
